﻿Imports System.Drawing
''' <summary>
''' 记录实际行信息的管理器
''' </summary>
''' <remarks></remarks>
Public Class RealLineManager
#Region "共通"
    ''' <summary>
    ''' 实际行列表
    ''' </summary>
    ''' <remarks>折行的时候，放入首行行号</remarks>
    Dim FirstMemoryNoList As New List(Of Integer)
    ''' <summary>
    ''' 在尾部添加记录
    ''' </summary>
    ''' <param name="FirstMemoryNo"></param>
    ''' <remarks></remarks>
    Sub Add(ByVal FirstMemoryNo As Integer)
        FirstMemoryNoList.Add(FirstMemoryNo)
    End Sub
    ''' <summary>
    ''' 在制定位置后插入记录
    ''' </summary>
    ''' <param name="NewLineNumber"></param>
    ''' <remarks></remarks>
    Sub Insert(ByVal NewLineNumber As Integer, ByVal MemoryNumber As Integer)
        'TODO: 有的地方不能用ADD方法，请检查一下
        FirstMemoryNoList.Insert(NewLineNumber - 1, MemoryNumber)
        '修正余下行的内容
        For i As Integer = NewLineNumber To FirstMemoryNoList.Count - 1
            FirstMemoryNoList(i) += 1
        Next
    End Sub
    ''' <summary>
    ''' 删除一个真实行
    ''' </summary>
    ''' <param name="realLineNo"></param>
    ''' <remarks></remarks>
    Sub RemoveAt(ByVal realLineNo As Integer, ByVal Delta As Integer)
        'TODO: 有的地方不能用ADD方法，请检查一下
        FirstMemoryNoList.RemoveAt(realLineNo - 1)
        '修正余下行的内容
        For i As Integer = realLineNo - 1 To FirstMemoryNoList.Count - 1
            FirstMemoryNoList(i) -= Delta
        Next
    End Sub
    ''' <summary>
    ''' 清空行信息列表
    ''' </summary>
    ''' <remarks></remarks>
    Sub Clear()
        FirstMemoryNoList.Clear()
    End Sub
    ''' <summary>
    ''' 获得实际行数量
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function Count() As Integer
        Return FirstMemoryNoList.Count
    End Function
    ''' <summary>
    ''' 更新真实行内存首行位置
    ''' </summary>
    ''' <param name="RealLineNo"></param>
    ''' <param name="FirstLineNo"></param>
    ''' <remarks></remarks>
    Sub Replace(ByVal RealLineNo As Integer, ByVal FirstLineNo As Integer)
        FirstMemoryNoList(RealLineNo - 1) = FirstLineNo
    End Sub
    ''' <summary>
    ''' 用更新量更新真实行内存首行位置
    ''' </summary>
    ''' <param name="RealLineNo"></param>
    ''' <param name="delta"></param>
    ''' <remarks></remarks>
    Sub ReplaceByDelta(ByVal RealLineNo As Integer, ByVal Delta As Integer)
        FirstMemoryNoList(RealLineNo - 1) += Delta
    End Sub
    ''' <summary>
    ''' 重置注释
    ''' </summary>
    ''' <param name="LineNumber"></param>
    ''' <remarks></remarks>
    Sub ResetBlockComment(ByVal LineNumber As Integer)
        Dim FirstLine As Line = ExDocument.MemoryLines(FirstMemoryNoList(LineNumber - 1) - 1)
        Dim mText As String = String.Empty
        For i As Integer = FirstLine.Real_MemoryStartLineNo To FirstLine.Real_MemoryEndLineNo
            mText &= ExDocument.GetMemoryLine(i).Text
        Next
        If Not (BlockCommentStartMark = String.Empty Or BlockCommentEndMark = String.Empty) Then
            If Left(mText.TrimStart, BlockCommentStartMark.Length) = BlockCommentStartMark Then
                FirstLine.Real_IsCommentStart = True
            End If
            If Right(mText.TrimEnd, BlockCommentEndMark.Length) = BlockCommentEndMark Then
                FirstLine.Real_IsCommentEnd = True
            End If
        End If
    End Sub
    ''' <summary>
    ''' 从真实行号来获得内存首行，进而可以获得详细信息
    ''' </summary>
    ''' <param name="LineNumber">真实行号</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function GetInfoLine(ByVal LineNumber As Integer) As Line
        Return ExDocument.MemoryLines(FirstMemoryNoList(LineNumber - 1) - 1)
    End Function
#End Region
#Region "文本选择"
    ''' <summary>
    ''' 选中文本
    ''' </summary>
    ''' <param name="LineNumber">真实行号</param>
    ''' <param name="SelStart">起始位置</param>
    ''' <param name="SelLength">长度</param>
    ''' <remarks></remarks>
    Sub SelectText(ByVal LineNumber As Integer, ByVal SelStart As Integer, ByVal SelLength As Integer)
        Dim StartPos As Point = GetMemPosByRealPos(New Point(SelStart, LineNumber))
        Dim EndPos As Point = GetMemPosByRealPos(New Point(SelStart + SelLength, LineNumber))
        If StartPos.Y = EndPos.Y Then
            ExDocument.GetMemoryLine(StartPos.Y).atomic_SelectText(StartPos.X, EndPos.X - StartPos.X)
        Else
            ExDocument.GetMemoryLine(StartPos.Y).atomic_SelectToEnd(StartPos.X)
            If EndPos.Y - StartPos.Y > 1 Then
                For i As Integer = StartPos.Y + 1 To EndPos.Y - 1
                    ExDocument.GetMemoryLine(i).atomic_SelectAll()
                Next
            End If
            ExDocument.GetMemoryLine(EndPos.Y).atomic_SelectToHeader(EndPos.X)
        End If
    End Sub
    ''' <summary>
    ''' 从行首到指定位置为选中位置
    ''' </summary>
    ''' <param name="CurrentXPos">指定位置</param>
    ''' <remarks>从1开始</remarks>
    Friend Sub SelectToHeader(ByVal LineNumber As Integer, ByVal CurrentXPos As Integer)
        Dim InlinePos As Point = GetMemPosByRealPos(New Point(CurrentXPos, LineNumber))
        Dim MemoryStartLineNo As Integer = ExDocument.MemoryLines(FirstMemoryNoList(LineNumber - 1) - 1).Real_MemoryStartLineNo
        If InlinePos.Y = MemoryStartLineNo Then
            ExDocument.GetMemoryLine(MemoryStartLineNo).atomic_SelectToHeader(InlinePos.X)
        Else
            For i As Integer = MemoryStartLineNo To InlinePos.Y - 1
                ExDocument.GetMemoryLine(i).atomic_SelectAll()
            Next
            ExDocument.GetMemoryLine(InlinePos.Y).atomic_SelectToHeader(InlinePos.X)
        End If
    End Sub
    ''' <summary>
    ''' 从指定位置选中到行尾
    ''' </summary>
    ''' <param name="CurrentXPos">指定位置</param>
    ''' <remarks></remarks>
    Friend Sub SelectToEnd(ByVal LineNumber As Integer, ByVal CurrentXPos As Integer)
        Dim InlinePos As Point = GetMemPosByRealPos(New Point(CurrentXPos, LineNumber))
        Dim MemoryEndLineNo As Integer = ExDocument.MemoryLines(FirstMemoryNoList(LineNumber - 1) - 1).Real_MemoryEndLineNo
        If InlinePos.Y = MemoryEndLineNo Then
            ExDocument.GetMemoryLine(MemoryEndLineNo).atomic_SelectToEnd(InlinePos.X)
        Else
            ExDocument.GetMemoryLine(InlinePos.Y).atomic_SelectToEnd(InlinePos.X)
            For i As Integer = InlinePos.Y + 1 To MemoryEndLineNo
                ExDocument.GetMemoryLine(i).atomic_SelectAll()
            Next
        End If
    End Sub
    ''' <summary>
    ''' 选中整行
    ''' </summary>
    ''' <remarks></remarks>
    Friend Sub SelectAll(ByVal LineNumber As Integer)
        Dim FirstLine As Line = ExDocument.MemoryLines(FirstMemoryNoList(LineNumber - 1) - 1)
        For i As Integer = FirstLine.Real_MemoryStartLineNo To FirstLine.Real_MemoryEndLineNo
            ExDocument.GetMemoryLine(i).atomic_SelectAll()
        Next
    End Sub
    ''' <summary>
    ''' 取消选中
    ''' </summary>
    ''' <remarks></remarks>
    Friend Sub UnSelectAll(ByVal LineNumber As Integer)
        Dim FirstLine As Line = ExDocument.MemoryLines(FirstMemoryNoList(LineNumber - 1) - 1)
        For i As Integer = FirstLine.Real_MemoryStartLineNo To FirstLine.Real_MemoryEndLineNo
            ExDocument.GetMemoryLine(i).atomic_UnSelectAll()
        Next
    End Sub
    ''' <summary>
    ''' 根据真实位置获得内存位置
    ''' </summary>
    ''' <param name="InputPos">真实行号</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function GetMemPosByRealPos(ByVal InputPos As Point) As Point
        Dim RowNum As Integer = 1
        Dim ColNum As Integer = 1
        Dim CharLength As Integer = InputPos.X - 1
        Dim strLine As String
        Dim FirstLine As Line = GetInfoLine(InputPos.Y)
        For i As Integer = FirstLine.Real_MemoryStartLineNo To FirstLine.Real_MemoryEndLineNo
            strLine = ExDocument.GetMemoryLine(i).Text
            If CharLength <= strLine.Length Then
                RowNum = i
                ColNum = CharLength + 1
                Exit For
            Else
                CharLength -= strLine.Length
            End If
        Next
        Return New Point(ColNum, RowNum)
    End Function
    ''' <summary>
    ''' 是否整个实际行被选中
    ''' </summary>
    ''' <param name="RealLineNumber">真实行号</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Function IsSelectWholeLine(ByVal RealLineNumber As Integer) As Boolean
        For i As Integer = GetInfoLine(RealLineNumber).Real_MemoryStartLineNo To _
                           GetInfoLine(RealLineNumber).Real_MemoryEndLineNo
            If ExDocument.GetMemoryLine(i).IsWholeSelected = False Then Return False
        Next
        Return True
    End Function
#End Region
End Class
